package com.zyfdroid.backupftpserver;


import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.usage.NetworkStatsManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;

import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile;
import com.zyfdroid.backupftpserver.ftplets.AnonymousUserManager;
import com.zyfdroid.backupftpserver.ftplets.MyFtpFileSystemFactory;

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authentication;
import org.apache.ftpserver.ftplet.AuthenticationFailedException;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.AuthorizationRequest;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpStatistics;
import org.apache.ftpserver.ftplet.User;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.impl.DefaultFtpServer;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.impl.BaseUser;
//import org.apache.log4j.BasicConfigurator;
import android.net.TrafficStats;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.List;

public class MainActivity extends Activity {

    TextView txtStatistic;

    @Override
    protected void onDestroy() {
        hWnd.removeCallbacks(timer);
        super.onDestroy();
    }

    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE" };


    public void verifyStoragePermissions() {
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M){return;}
        try {
            //检测是否有写的权限
            int permission = checkSelfPermission(
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 没有写的权限，去申请写的权限，会弹出对话框
                requestPermissions( PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    ToggleButton tb;

    Handler hWnd = new Handler();

    long downbegin=0;
    long upbegin=0;

    float animation=0f;

    View curOuter,curInner;

    float rotateU=0f;
    float rotateD=0f;

    float rotateSmoothFactor = 0.03f;

    long lastsecond=0;

    float vd=0;
    float vu=0;

    double lsd;
    double lsu;

    float dvd,dvu;

    long lastU,lastD;

    Runnable timer = new Runnable() {
        @Override
        public void run() {

            if(isStarted()){
                long down = TrafficStats.getUidRxBytes(getApplicationInfo().uid) - downbegin;
                long up = TrafficStats.getUidTxBytes(getApplicationInfo().uid) - upbegin;


                if(lastsecond != System.currentTimeMillis()/1000){
                    lastsecond = System.currentTimeMillis()/1000;
                    txtStatistic.setText("↓ "+ Formatter.formatFileSize(MainActivity.this, down  -lastD)+"/s  ↑ " + Formatter.formatFileSize(MainActivity.this,up - lastU)+"/s");
                    lastU = up;
                    lastD = down;
                }

                if(animation<1){
                    animation+=(1-animation)*0.1f;
                    if(animation>1){
                        animation=1;
                    }
                }



                double d = (down) / 1048576d * 360 - lsd;
                double u = (-up) / 1048576d * 360 - lsu;
                lsd = (down) / 1048576d * 360;
                lsu = (-up) / 1048576d * 360;

                vd =(float) Math.atan(d);
                vu =(float) Math.atan(u);

                dvd += (vd - dvd) * 0.1f;
                dvu += (vu - dvu) * 0.1f;

                rotateD -= dvd; //(((float)d) - rotateD) * rotateSmoothFactor;
                rotateU -= dvu; //(((float)u) - rotateU) * rotateSmoothFactor;

                if(rotateD < 0){rotateD+=360;}
                if(rotateU > 360){rotateD-=360;}

                curInner.setRotation(rotateD);
                curOuter.setRotation(rotateU);
            }
            else{
                if(animation>0){
                    animation-=(animation) * 0.1f;
                    if(animation<0){
                        animation=0;
                    }
                }
                txtStatistic.setText("");
                ((TextView)findViewById(R.id.txtIps)).setElevation(0);
            }
            curInner.setScaleX(animation);
            curInner.setScaleY(animation);
            curOuter.setScaleX(animation);
            curOuter.setScaleY(animation);
            txtIp.setElevation(5 * getResources().getDisplayMetrics().density * animation);
            hWnd.postDelayed(timer,16);
        }
    };
    TextView txtIp;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        verifyStoragePermissions();

        curInner = findViewById(R.id.cirInner);
        curOuter = findViewById(R.id.cirOuter);
        txtIp = findViewById(R.id.txtIps);

        //BasicConfigurator.configure();
        txtStatistic = findViewById(R.id.txtStatistic);

        tb = findViewById(R.id.btnToggle);
        tb.setChecked(isStarted());
        animation=isStarted() ? 1 : 0;
        txtStatistic.setKeepScreenOn(isStarted());
        tb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){
                    start();
                }
                else{
                    stop();
                }
                txtStatistic.setKeepScreenOn(isChecked);
                ((TextView)findViewById(R.id.txtIps)).setText(getLocalIPAddress());
            }
        });
        hWnd.postDelayed(timer,500);
    }

    @Override
    protected void onResume() {
        super.onResume();
        ((TextView)findViewById(R.id.txtIps)).setText(getLocalIPAddress());
    }

    long t = 0;

    public boolean isStarted() {
        return ServerService.fs!=null;
    }
    public void start(){
        if(!isStarted()) {
            startService(new Intent(this,ServerService.class));
            downbegin = TrafficStats.getUidRxBytes(getApplicationInfo().uid);
            upbegin = TrafficStats.getUidTxBytes(getApplicationInfo().uid);
            lastD = 0;
            lastU = 0;
            dvd=30;
            dvu=-30;
            rotateD = -90f;
            rotateU = 90f;
        }
    }

    public void stop(){
        if(isStarted()){
            stopService(new Intent(this,ServerService.class));
        }
    }

    public String getLocalIPAddress()
    {
        String result="";
        try
        {
            for (Enumeration<NetworkInterface> mEnumeration = NetworkInterface.getNetworkInterfaces(); mEnumeration.hasMoreElements();)               {
                NetworkInterface intf = mEnumeration.nextElement();
                for (Enumeration<InetAddress> enumIPAddr = intf.getInetAddresses(); enumIPAddr.hasMoreElements();)
                {
                    InetAddress inetAddress = enumIPAddr.nextElement();
                    //如果不是回环地址
                    if (!inetAddress.isLoopbackAddress() && !inetAddress.getHostAddress().contains(":"))
                    {
                        result+= "ftp://"+inetAddress.getHostAddress()+":8421/\n";
                    }
                }
            }
        }
        catch (SocketException ex)
        {
            android.util.Log.e("Error", ex.toString());
        }
        if(result.trim().isEmpty()){
            return "没有可用的网络地址";
        }
        return result.trim();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuItem m = menu.add("添加其它文件夹");
        m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(@NonNull MenuItem item) {
                Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
                startActivityForResult(i,REQ_OPEN_SAF);
                return false;
            }
        });
        m = menu.add("管理已添加的文件夹");
        m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(@NonNull MenuItem item) {
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("已添加的文件夹列表")
                        .setAdapter(new ManageFoldersDialogAdapter(),null)
                        .setNegativeButton("关闭",null)
                        .create().show();

                return false;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }

    private static final int REQ_OPEN_SAF = 216;
    
    @SuppressLint("WrongConstant")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == REQ_OPEN_SAF && resultCode == RESULT_OK){
            Uri uri = data.getData();
            if (uri != null) {
                // 保存获取的目录权限
                final int takeFlags = data.getFlags()
                        & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                getContentResolver().takePersistableUriPermission(uri,  takeFlags);
                // 保存uri
                try {

                    new SAFHelper(this).registerEntry(uri.toString());
                    Toast.makeText(this, "添加成功！", Toast.LENGTH_SHORT).show();
                }catch (UnsupportedOperationException ex){
                    Toast.makeText(this, ex.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
            return;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }


    class ManageFoldersDialogAdapter extends BaseAdapter implements View.OnClickListener {
        SAFHelper safHelper;
        List<SAFHelper.SAFEntry> entries;

        public ManageFoldersDialogAdapter(){
            safHelper = new SAFHelper(MainActivity.this);
            entries = safHelper.getAllSafs();
        }

        @Override
        public void notifyDataSetChanged() {
            entries = safHelper.getAllSafs();
            super.notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return entries.size();
        }

        @Override
        public SAFHelper.SAFEntry getItem(int position) {
            return entries.get(position);
        }


        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null){
                convertView = getLayoutInflater().inflate(R.layout.list_items,null,false);
                convertView.findViewById(R.id.btnDelete).setOnClickListener(this);
            }
            SAFHelper.SAFEntry item = getItem(position);
            ((TextView) convertView.findViewById(R.id.lblDisplayName)).setText(item.displayName);
            ((TextView) convertView.findViewById(R.id.lblDocumentTreeUri)).setText(item.uri);
            convertView.findViewById(R.id.btnDelete).setTag(item);
            return convertView;
        }

        @Override
        public void onClick(View v) {
            if(v.getTag() instanceof SAFHelper.SAFEntry){
                final SAFHelper.SAFEntry it = (SAFHelper.SAFEntry) v.getTag();
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("是否移除这个文件夹")
                        .setMessage("是否从FTP虚拟文件系统中移除文件夹 "+it.displayName)
                        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                safHelper.deleteEntry(it);
                                notifyDataSetChanged();
                            }
                        })
                        .setNegativeButton(android.R.string.no,null)
                        .create().show();
            }
        }
    }
}